home *** CD-ROM | disk | FTP | other *** search
- /*
- * fsNameOps.c --
- *
- * This has procedures for the operations done on file names
- * like open and remove. The name lookups are done via
- * Fsprefix_LookupOperation which uses the prefix table to choose the server.
- *
- * Copyright (C) 1987 Regents of the University of California
- * All rights reserved.
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fs/fsNameOps.c,v 9.4 91/09/10 18:22:35 rab Exp $ SPRITE (Berkeley)";
- #endif not lint
-
-
- #include <sprite.h>
- #include <fs.h>
- #include <fsio.h>
- #include <fsutil.h>
- #include <fsNameOps.h>
- #include <fsStat.h>
- #include <fsprefix.h>
- #include <proc.h>
- #include <rpc.h>
- #include <dbg.h>
- #include <string.h>
- #include <stdio.h>
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_Open --
- *
- * This routine sets up a Fs_Stream object for the named file. The
- * parameters specify the manner in which the stream will be used and
- * a set of permission bits in case a file needs to be created for
- * the stream.
- *
- * Results:
- * An error code, and a pointer to a Fs_Stream object for the file.
- * This is used in further operations on the file and is released
- * with Fs_Close
- *
- * Side effects:
- * The stream is opened.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fs_Open(name, useFlags, type, permissions, streamPtrPtr)
- char *name; /* The name of the file to open */
- register int useFlags; /* Indicates read/write etc. the valid bits
- * to include are defined in fs.h */
- int type; /* If FS_FILE then any type of file can be
- * opened, except if useFlags includes
- * FS_CREATE then a regular file will be
- * created. Otherwise only the specified
- * type can be opened (or created). */
- int permissions; /* A mask indicating the permission bits to
- * turn on if the file gets created */
- Fs_Stream **streamPtrPtr; /* Contents set to point to a valid stream
- * or NIL if there was an error. */
- {
- register Fs_Stream *streamPtr; /* Local copy of stream pointer */
- ReturnStatus status; /* Return error code from RPC */
- Fs_OpenArgs openArgs; /* Packaged up parameters */
- Fs_OpenResults openResults; /* Packaged up results */
- Proc_ControlBlock *procPtr; /* Used to get process IDs */
- Fs_NameInfo *nameInfoPtr; /* Used to track name and prefix */
-
- *streamPtrPtr = (Fs_Stream *)NIL;
-
- if ((useFlags & FS_EXECUTE) && (useFlags & (FS_WRITE | FS_CREATE))) {
- return(FS_INVALID_ARG);
- }
-
- /*
- * Override the type if user flags indicate special files.
- */
- if (useFlags & FS_NAMED_PIPE_OPEN) {
- printf( "Named pipes (%s) not implemented\n", name);
- return(FS_INVALID_ARG);
- } else if (useFlags & FS_PDEV_MASTER) {
- type = FS_PSEUDO_DEV;
- } else if (useFlags & FS_PFS_MASTER) {
- type = FS_REMOTE_LINK;
- useFlags &= ~FS_FOLLOW;
- }
- /*
- * Make sure we check for write permission before truncating.
- */
- if (useFlags & FS_TRUNC) {
- useFlags |= FS_WRITE;
- }
-
- /*
- * Set up arguments to the Domain specific open routine. The domain
- * open routine returns streamData used to set up the I/O handle
- * by the client open routine called below. The stream's nameInfo is
- * set up as a side effect of going through Fsprefix_LookupOperation.
- */
- procPtr = Proc_GetEffectiveProc();
- if (type != FS_SYMBOLIC_LINK && type != FS_REMOTE_LINK) {
- openArgs.permissions = permissions & procPtr->fsPtr->filePermissions;
- } else {
- openArgs.permissions = permissions;
- }
- openArgs.useFlags = useFlags;
- openArgs.type = type;
- openArgs.clientID = rpc_SpriteID;
- if (procPtr->genFlags & PROC_FOREIGN) {
- openArgs.migClientID = procPtr->peerHostID;
- } else {
- openArgs.migClientID = rpc_SpriteID;
- }
- openResults.streamData = (ClientData) NIL;
- Fs_SetIDs(procPtr, &openArgs.id);
- nameInfoPtr = mnew(Fs_NameInfo);
-
- status = Fsprefix_LookupOperation(name, FS_DOMAIN_OPEN, useFlags & FS_FOLLOW,
- (Address)&openArgs, (Address)&openResults, nameInfoPtr);
- if (status == SUCCESS) {
- /*
- * Install the stream and then call the client open procedure
- * to complete the setup of the stream's I/O handle
- */
- streamPtr = Fsio_StreamAddClient(&openResults.streamID, rpc_SpriteID,
- (Fs_HandleHeader *)NIL,
- useFlags, name, (Boolean *)NIL, (Boolean *)NIL);
- streamPtr->nameInfoPtr = nameInfoPtr;
- Fsutil_HandleUnlock(streamPtr);
- status = (*fsio_StreamOpTable[openResults.ioFileID.type].ioOpen)
- (&openResults.ioFileID, &streamPtr->flags, rpc_SpriteID,
- openResults.streamData, name, &streamPtr->ioHandlePtr);
- if (status == SUCCESS) {
- if (streamPtr->flags & FS_TRUNC) {
- (void)Fs_TruncStream(streamPtr, 0);
- }
- *streamPtrPtr = streamPtr;
- switch (useFlags & (FS_READ | FS_WRITE)) {
- case FS_READ:
- fs_Stats.cltName.numReadOpens ++;
- break;
- case FS_WRITE:
- fs_Stats.cltName.numWriteOpens ++;
- break;
- case (FS_READ | FS_WRITE):
- fs_Stats.cltName.numReadWriteOpens ++;
- break;
- default:
- break;
- }
- } else {
- /*
- * Client open procedure failed. Clean up the stream.
- */
- Fsutil_HandleLock(streamPtr);
- (void)Fsio_StreamClientClose(&streamPtr->clientList, rpc_SpriteID);
- Fsio_StreamDestroy(streamPtr);
- }
- } else {
- free((Address)nameInfoPtr);
- }
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_SetIDs --
- *
- * Get user ID and group IDs from the proc table. The FsUserID
- * struct includes storage for the list of groups. Alternatively,
- * it could contain a pointer to the groups in the proc table.
- *
- * TODO: Byte the bullet and figure out a nice way to pass a
- * variable length list of groups around. Then this procedure
- * would not be needed, and the Fs_ProcessState could be
- * referenced directly. The ugliest place to do all this is
- * in the RPC stubs.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Instantiate *idPtr to hold the user and group IDs of the current proc.
- *
- *----------------------------------------------------------------------
- */
- void
- Fs_SetIDs(procPtr, idPtr)
- Proc_ControlBlock *procPtr;
- Fs_UserIDs *idPtr;
- {
- register Fs_ProcessState *fsPtr;
- register int *procGroupIDs;
- register int *groupPtr;
- register int i;
-
- if (procPtr == (Proc_ControlBlock *)NIL) {
- procPtr = Proc_GetEffectiveProc();
- }
- idPtr->user = procPtr->effectiveUserID;
-
- fsPtr = procPtr->fsPtr;
- if (fsPtr == (Fs_ProcessState *)NIL) {
- /*
- * Exiting processes remove swap files after clearing fs state.
- */
- idPtr->numGroupIDs = 0;
- procGroupIDs = (int *)NIL;
- } else {
- idPtr->numGroupIDs = fsPtr->numGroupIDs;
- procGroupIDs = fsPtr->groupIDs;
- }
- for (i = 0, groupPtr = idPtr->group; i < FS_NUM_GROUPS; i++, groupPtr++) {
- /*
- * The file system state record supports a variable length array of
- * group IDs but here we truncate it...
- */
- if (i < idPtr->numGroupIDs) {
- *groupPtr = *procGroupIDs;
- procGroupIDs++;
- } else {
- *groupPtr = -1;
- }
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_Remove --
- *
- * Remove the named file. Because each entry in a directory is only
- * one of many posible references, the disk space for the file may or
- * may not be freed after this call. Only when the last link to
- * the file is removed is the disk space freed up. This does not
- * follow links so that links are removed instead of the file
- * they reference.
- *
- * Results:
- * An error code.
- *
- * Side effects:
- * The file is removed
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fs_Remove(name)
- char *name; /* The name of the file to remove */
- {
- ReturnStatus status;
- Fs_LookupArgs lookupArgs;
- Proc_ControlBlock *procPtr = Proc_GetEffectiveProc();
-
- lookupArgs.useFlags = FS_DELETE;
- Fs_SetIDs(procPtr, &lookupArgs.id);
- lookupArgs.clientID = rpc_SpriteID;
- if (procPtr->genFlags & PROC_FOREIGN) {
- lookupArgs.migClientID = procPtr->peerHostID;
- } else {
- lookupArgs.migClientID = rpc_SpriteID;
- }
- fs_Stats.cltName.removes++;
- status = Fsprefix_LookupOperation(name, FS_DOMAIN_REMOVE, 0,
- (Address)&lookupArgs, (Address)NIL, (Fs_NameInfo *)NIL);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_RemoveDir --
- *
- * Remove the named directory. It must be empty, that is it should
- * only contain entries for itself (.) and its parent (..).
- *
- * Results:
- * An error code.
- *
- * Side effects:
- * The directory is removed if possible
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fs_RemoveDir(name)
- char *name; /* The name of the directory to remove */
- {
- ReturnStatus status;
- Fs_LookupArgs lookupArgs;
- Proc_ControlBlock *procPtr = Proc_GetEffectiveProc();
-
- lookupArgs.useFlags = FS_DELETE;
- Fs_SetIDs(procPtr, &lookupArgs.id);
- lookupArgs.clientID = rpc_SpriteID;
- if (procPtr->genFlags & PROC_FOREIGN) {
- lookupArgs.migClientID = procPtr->peerHostID;
- } else {
- lookupArgs.migClientID = rpc_SpriteID;
- }
- fs_Stats.cltName.removeDirs++;
- status = Fsprefix_LookupOperation(name, FS_DOMAIN_REMOVE_DIR, 0,
- (Address)&lookupArgs, (Address)NIL, (Fs_NameInfo *)NIL);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_MakeDevice --
- *
- * Make the named device file. This is the procedure which
- * does the actual work for the Fs_MakeDevice system call.
- *
- * Results:
- * An error code.
- *
- * Side effects:
- * The device file is made
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fs_MakeDevice(name, devicePtr, permissions)
- char *name; /* The name of the directory to make */
- Fs_Device *devicePtr; /* Specifies device info */
- int permissions; /* The permissions for the new directory */
- {
- ReturnStatus status; /* Return error code */
- Fs_MakeDeviceArgs makeDevArgs;/* Packaged up parameters */
- Proc_ControlBlock *procPtr; /* Used to get process IDs */
-
- if (((devicePtr->serverID != FS_LOCALHOST_ID) &&
- (devicePtr->serverID <= 0)) ||
- (devicePtr->type < 0) ||
- (devicePtr->unit < 0)) {
- return(FS_INVALID_ARG);
- }
- procPtr = Proc_GetEffectiveProc();
- makeDevArgs.device = *devicePtr;
- makeDevArgs.open.permissions= permissions & procPtr->fsPtr->filePermissions;
- Fs_SetIDs(procPtr, &makeDevArgs.open.id);
- makeDevArgs.open.clientID = rpc_SpriteID;
- if (procPtr->genFlags & PROC_FOREIGN) {
- makeDevArgs.open.migClientID = procPtr->peerHostID;
- } else {
- makeDevArgs.open.migClientID = rpc_SpriteID;
- }
-
- fs_Stats.cltName.makeDevices++;
- status = Fsprefix_LookupOperation(name, FS_DOMAIN_MAKE_DEVICE, 0,
- (Address)&makeDevArgs, (Address)NIL, (Fs_NameInfo *)NIL);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_MakeDir --
- *
- * Make the named directory. This is the procedure which
- * does the actual work for the Fs_MakeDir system call.
- *
- * Results:
- * An error code.
- *
- * Side effects:
- * The directory is made
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fs_MakeDir(name, permissions)
- char *name; /* The name of the directory to make */
- int permissions; /* The permissions for the new directory */
- {
- ReturnStatus status; /* Return error code from RPC */
- Fs_OpenArgs openArgs; /* Packaged up parameters */
- Proc_ControlBlock *procPtr; /* Used to get process IDs */
-
- procPtr = Proc_GetEffectiveProc();
- openArgs.useFlags = FS_CREATE | FS_EXCLUSIVE | FS_FOLLOW ;
- openArgs.permissions = permissions & procPtr->fsPtr->filePermissions;
- openArgs.type = FS_DIRECTORY;
- Fs_SetIDs(procPtr, &openArgs.id);
- openArgs.clientID = rpc_SpriteID;
- if (procPtr->genFlags & PROC_FOREIGN) {
- openArgs.migClientID = procPtr->peerHostID;
- } else {
- openArgs.migClientID = rpc_SpriteID;
- }
- fs_Stats.cltName.makeDirs++;
- status = Fsprefix_LookupOperation(name, FS_DOMAIN_MAKE_DIR, FS_FOLLOW,
- (Address)&openArgs, (Address)NIL, (Fs_NameInfo *)NIL);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_ChangeDir --
- *
- * Change the process's current directory. This opens the
- * new current directory, and if that's successful the
- * old one is closed.
- *
- * Results:
- * An error code.
- *
- * Side effects:
- * Change the current directory.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fs_ChangeDir(pathName)
- char *pathName;
- {
- register Fs_ProcessState *fsPtr;
- Fs_Stream *newCwdPtr; /* A stream is used because it has
- * a reference count and can be
- * closed with existing routines. */
- ReturnStatus status;
-
- fsPtr = (Proc_GetEffectiveProc())->fsPtr;
-
- /*
- * FS_EXECUTE permission needed to change to a directory.
- */
- newCwdPtr = (Fs_Stream *)NIL;
- fs_Stats.cltName.chdirs++;
- status = Fs_Open(pathName, FS_EXECUTE | FS_FOLLOW, FS_DIRECTORY, 0,
- &newCwdPtr);
- if (status) {
- return(status);
- }
- (void)Fs_Close(fsPtr->cwdPtr);
- fsPtr->cwdPtr = newCwdPtr;
- return(SUCCESS);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_Trunc --
- *
- * Truncate a file to a given length given its pathname.
- *
- * Results:
- * An error code
- *
- * Side effects:
- * The files length gets set and any data beyond that is deleted.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fs_Trunc(pathName, length)
- char *pathName;
- int length;
- {
- Fs_Stream *streamPtr;
- ReturnStatus status;
-
- streamPtr = (Fs_Stream *)NIL;
- status = Fs_Open(pathName, FS_WRITE | FS_FOLLOW, FS_FILE, 0, &streamPtr);
- if (status != SUCCESS) {
- return(status);
- }
- status = Fs_TruncStream(streamPtr, length);
- (void)Fs_Close(streamPtr);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_TruncStream --
- *
- * Truncate a file to a given length given an open stream.
- * This is a thin layer on top of Fs_IOControl that is called
- * from Fs_Trunc and from Fs_Open.
- *
- * Results:
- * An error code
- *
- * Side effects:
- * The files length gets set and any data beyond that is deleted.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fs_TruncStream(streamPtr, length)
- Fs_Stream *streamPtr;
- int length;
- {
- ReturnStatus status;
- Proc_ControlBlock *procPtr = Proc_GetEffectiveProc();
- Fs_IOCParam ioctl;
- Fs_IOReply reply;
-
- if (length < 0) {
- return(GEN_INVALID_ARG);
- }
- ioctl.command = IOC_TRUNCATE;
- ioctl.inBuffer = (Address)&length;
- ioctl.inBufSize = sizeof(int);
- ioctl.outBuffer = (Address) NIL;
- ioctl.outBufSize = 0;
- ioctl.format = mach_Format;
- ioctl.procID = procPtr->processID;
- ioctl.familyID = procPtr->familyID;
- ioctl.uid = procPtr->effectiveUserID;
- ioctl.flags = 0;
-
- status = Fs_IOControl(streamPtr, &ioctl, &reply);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_GetAttributes --
- *
- * Get the attributes of a file given its name. First the name server
- * is contacted to get the initial version of the attributes. Then
- * the I/O server is contacted to update attributes like the
- * access and modify times.
- *
- * Results:
- * An error code and the attributes.
- *
- * Side effects:
- * None here.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Fs_GetAttributes(pathName, fileOrLink, attrPtr)
- char *pathName;
- int fileOrLink; /* FS_ATTRIB_FILE or FS_ATTRIB_LINK */
- Fs_Attributes *attrPtr;
- {
- ReturnStatus status;
- Fs_OpenArgs openArgs;
- Proc_ControlBlock *procPtr = Proc_GetEffectiveProc();
- Fs_GetAttrResults getAttrResults; /* References attrPtr and ioFileID */
- Fs_FileID ioFileID; /* Returned from name server, indicates
- * who the I/O server is. */
-
- openArgs.useFlags = (fileOrLink == FS_ATTRIB_LINK) ? 0 : FS_FOLLOW;
- openArgs.permissions = 0;
- openArgs.type = FS_FILE;
- openArgs.clientID = rpc_SpriteID;
- Fs_SetIDs(procPtr, &openArgs.id);
- if (procPtr->genFlags & PROC_FOREIGN) {
- openArgs.migClientID = procPtr->peerHostID;
- } else {
- openArgs.migClientID = rpc_SpriteID;
- }
-
- getAttrResults.attrPtr = attrPtr;
- getAttrResults.fileIDPtr = &ioFileID;
-
- /*
- * Get an initial version of the attributes from the name server.
- */
- fs_Stats.cltName.getAttrs++;
- status = Fsprefix_LookupOperation(pathName, FS_DOMAIN_GET_ATTR, openArgs.useFlags,
- (Address)&openArgs, (Address)&getAttrResults,
- (Fs_NameInfo *)NIL);
- if ((status == SUCCESS) &&
- (ioFileID.type > 0 && ioFileID.type <= FSIO_NUM_STREAM_TYPES)) {
- /*
- * Update those with attributes cached at the I/O server.
- * This is suppressed by setting the ioFileID.type < 0
- */
- fs_Stats.cltName.getIOAttrs++;
- status = (*fsio_StreamOpTable[ioFileID.type].getIOAttr)
- (&ioFileID, rpc_SpriteID, attrPtr);
- #ifdef lint
- status = Fsrmt_GetIOAttr(&ioFileID, rpc_SpriteID, attrPtr);
- status = FsrmtFileGetIOAttr(&ioFileID, rpc_SpriteID, attrPtr);
- status = Fsio_DeviceGetIOAttr(&ioFileID, rpc_SpriteID, attrPtr);
- status = Fsio_PipeGetIOAttr(&ioFileID, rpc_SpriteID, attrPtr);
- #endif lint
- }
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_SetAttributes --
- *
- * Set some attributes of a file given its name. The input contains
- * the complete set of attributes for the file but not all of these
- * are affected by this call. Ie. the user can't change everything.
- * The name server is contacted first to set attributes file descriptor,
- * then the I/O server is contacted to update cached attributes.
- *
- * Results:
- * An error code
- *
- * Side effects:
- * See FsLocalSetAttrID for which attributes get updated at the
- * file server.
- *
- * If the operation is successful, the count of setAttrs is incremented.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fs_SetAttributes(pathName, fileOrLink, attrPtr, flags)
- char *pathName;
- int fileOrLink;
- Fs_Attributes *attrPtr;
- int flags;
- {
- register ReturnStatus status;
- Proc_ControlBlock *procPtr = Proc_GetEffectiveProc();
- Fs_SetAttrArgs setAttrArgs; /* Bundled openArgs and attributes */
- Fs_OpenArgs *openArgsPtr; /* Pointer into setAttrArgs */
- Fs_FileID ioFileID; /* Used to get to I/O server */
-
- openArgsPtr = &setAttrArgs.openArgs;
- openArgsPtr->useFlags = FS_OWNERSHIP;
- if (fileOrLink == FS_ATTRIB_FILE) {
- openArgsPtr->useFlags |= FS_FOLLOW;
- }
- openArgsPtr->permissions = 0;
- openArgsPtr->type = FS_FILE;
- openArgsPtr->clientID = rpc_SpriteID;
- Fs_SetIDs(procPtr, &openArgsPtr->id);
- if (procPtr->genFlags & PROC_FOREIGN) {
- openArgsPtr->migClientID = procPtr->peerHostID;
- } else {
- openArgsPtr->migClientID = rpc_SpriteID;
- }
-
- /*
- * This copy is done here to avoid doing it in the client RPC stub.
- */
- setAttrArgs.attr = *attrPtr;
- setAttrArgs.flags = flags;
-
- /*
- * Set the attributes at the name server. We get in return a fileID
- * for the actual device which specifies a serverID.
- */
- fs_Stats.cltName.setAttrs++;
- status = Fsprefix_LookupOperation(pathName, FS_DOMAIN_SET_ATTR, 0,
- (Address)&setAttrArgs, (Address)&ioFileID,
- (Fs_NameInfo *)NIL);
- if ((status == SUCCESS) &&
- (ioFileID.type > 0 && ioFileID.type <= FSIO_NUM_STREAM_TYPES)) {
- /*
- * Set the attributes at the I/O server.
- */
- fs_Stats.cltName.setIOAttrs++;
- status = (*fsio_StreamOpTable[ioFileID.type].setIOAttr)
- (&ioFileID, attrPtr, flags);
- #ifdef lint
- status = Fsrmt_SetIOAttr(&ioFileID, attrPtr, flags);
- status = FsrmtFileSetIOAttr(&ioFileID, attrPtr, flags);
- status = Fsio_DeviceSetIOAttr(&ioFileID, attrPtr, flags);
- status = Fsio_PipeSetIOAttr(&ioFileID, attrPtr, flags);
- #endif lint
- }
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_HardLink --
- *
- * Make two pathnames refer to the same file. The pathnames are
- * restricted to be in the same domain, ie. stored on the same
- * disk pack, so the file server can make the link.
- *
- * Results:
- * SUCCESS if the link was made. FS_CANT_LINK if the pathnames
- * are not in the same domain.
- *
- * Side effects:
- * Cause the two pathnames to refer to the same file.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fs_HardLink(pathName, linkName)
- char *pathName; /* Name of the existing file */
- char *linkName; /* Name of the file to create which is a link to
- * the existing file */
- {
- ReturnStatus status;
- Fs_LookupArgs lookupArgs;
- Proc_ControlBlock *procPtr = Proc_GetEffectiveProc();
-
- lookupArgs.useFlags = FS_LINK;
- Fs_SetIDs(procPtr, &lookupArgs.id);
- lookupArgs.clientID = rpc_SpriteID;
- if (procPtr->genFlags & PROC_FOREIGN) {
- lookupArgs.migClientID = procPtr->peerHostID;
- } else {
- lookupArgs.migClientID = rpc_SpriteID;
- }
- fs_Stats.cltName.hardLinks++;
- status = Fsprefix_TwoNameOperation(FS_DOMAIN_HARD_LINK, pathName, linkName,
- &lookupArgs);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_Rename --
- *
- * Change the name of a file. This is complicated because the files
- * can only be in the same domain. This is not directly evident.
- *
- * Results:
- * SUCCESS if the name was changed.
- *
- * Side effects:
- * Change the name of a file.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fs_Rename(pathName, newName)
- char *pathName; /* Name of the existing file */
- char *newName; /* The new pathname for the file */
- {
- ReturnStatus status;
- Fs_LookupArgs lookupArgs;
- Proc_ControlBlock *procPtr = Proc_GetEffectiveProc();
-
- lookupArgs.useFlags = FS_LINK | FS_RENAME;
- Fs_SetIDs(procPtr, &lookupArgs.id);
- lookupArgs.clientID = rpc_SpriteID;
- if (procPtr->genFlags & PROC_FOREIGN) {
- lookupArgs.migClientID = procPtr->peerHostID;
- } else {
- lookupArgs.migClientID = rpc_SpriteID;
- }
- fs_Stats.cltName.renames++;
- status = Fsprefix_TwoNameOperation(FS_DOMAIN_RENAME, pathName, newName,
- &lookupArgs);
- return(status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_SymLink --
- *
- * Create a symbolic link file by writing the name of the target
- * file (including the NULL) into the link file. This only
- * succeeds if the link file does not already exist.
- *
- * Results:
- * SUCCESS if the link was created.
- *
- * Side effects:
- * Create the file and write the link name into it.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Fs_SymLink(targetName, linkName, remoteFlag)
- char *targetName; /* Name of the file to link to */
- char *linkName; /* The name of the new link file that's created */
- Boolean remoteFlag; /* TRUE => link will be a REMOTE_LINK */
- {
- ReturnStatus status;
- Fs_Stream *streamPtr;
- int length;
-
- if (remoteFlag) {
- /*
- * Could check for super-user only here.
- */
- if (targetName[0] != '/') {
- /*
- * Remote links must be absolute. They should also be circular,
- * but that is harder to check.
- */
- return(FS_INVALID_ARG);
- }
- }
- fs_Stats.cltName.symLinks++;
- status = Fs_Open(linkName, FS_CREATE | FS_WRITE | FS_EXCLUSIVE,
- (remoteFlag ? FS_REMOTE_LINK : FS_SYMBOLIC_LINK),
- 0777, &streamPtr);
- if (status == SUCCESS) {
- length = strlen(targetName) + 1; /* FIX */
- status = Fs_Write(streamPtr, targetName, 0, &length);
- (void)Fs_Close(streamPtr);
- }
- return(status);
- }
-